﻿using System;
using System.Collections.Generic;

namespace Sebastof.Types {
	/// <summary>
	/// Set of new objects.
	/// </summary>
	[Serializable]
	public class NewObjectSet : BaseChangetSet {
		#region Public Properties

		/// <summary>
		/// type of the object
		/// </summary>
		public Type type { get; set; }

		/// <summary>
		/// The id of the object
		/// </summary>
		public string oid { get; set; }

		/// <summary>
		/// Holds normal field value data
		/// </summary>
		public List<KeyValuePair<string, object>> normalcontent { get; set; }

		/// <summary>
		/// Holds data stored in the InterLinqApplicationObject data container
		/// </summary>
		public List<KeyValuePair<string, object>> interlinqcontent { get; set; }

		#endregion

		#region Public Methods

		public NewObjectSet() {
			ChangetSetType = EChangetSetType.New;
		}

		public override string ToString() {
			return string.Format("OID: '{0}', Adding Object of Type '{1}'", oid, type);
		}

		#endregion
	}

	/// <summary>
	/// A change set for normal changes (meaning value changes).
	/// </summary>
	[Serializable]
	public class ChangeSet : BaseChangetSet {
		#region Public Properties

		/// <summary>
		/// The type of the object
		/// </summary>
		public Type otype { get; set; }

		/// <summary>
		/// The id of the object
		/// </summary>
		public object oid { get; set; }

		/// <summary>
		/// The field of the object that was changes
		/// </summary>
		public string field { get; set; }

		/// <summary>
		/// The new value of the field
		/// </summary>
		public object newvalue { get; set; }

		/// <summary>
		/// Current version of the object.
		/// (Will be used by the server to compare if the server side object
		/// has not changed since the client loaded his version).
		/// </summary>
		public object version { get; set; }

		#endregion

		#region Public Methods

		public ChangeSet() {
			ChangetSetType = EChangetSetType.Change;
		}

		public override string ToString() {
			return string.Format("OID: '{0}', Changing Field '{1}' to '{2}'", oid, field, newvalue);
		}

		#endregion
	}

	/// <summary>
	/// The operation that was taken on a collection.
	/// </summary>
	public enum ECollectionChangeOperation {
		Set,
		Insert,
		InsertAt,
		Remove,
		RemoveAt
	}

	/// <summary>
	/// A change set holding information about changes in collections.
	/// </summary>
	[Serializable]
	public class ChangeCollectionSet : BaseChangetSet {
		#region Public Properties

		/// <summary>
		/// The id of the object holding the collection
		/// </summary>
		public object oidOfCollectionObject { get; set; }

		/// <summary>
		/// Field, of the object holding the collection, which references the collection
		/// </summary>
		public string fieldContainingCollection { get; set; }

		/// <summary>
		/// The index of the collection on which operation was taken.
		/// </summary>
		public int indexToOperateOn { get; set; }

		/// <summary>
		/// The operation that was taken on the collection
		/// </summary>
		public ECollectionChangeOperation operation { get; set; }

		/// <summary>
		/// The new value, if necessary, of the collection at the index position.
		/// </summary>
		public object newvalue { get; set; }

		#endregion

		#region Public Methods

		public ChangeCollectionSet() {
			ChangetSetType = EChangetSetType.ChangeCollection;
		}

		public override string ToString() {
			return string.Format("OID: '{0}', Collection '{1}' changed. Operation '{2}', Index '{3}', NewValue '{4}'",
								  oidOfCollectionObject, fieldContainingCollection, operation, indexToOperateOn, newvalue);
		}

		#endregion
	}

	/// <summary>
	/// A change set holding objects of deletion.
	/// Type and object identifier is everything we need 
	/// to delet an object.
	/// </summary>
	[Serializable]
	public class DeleteObjectSet : BaseChangetSet {
		#region Public Properties

		public Type type { get; set; }
		public string oid { get; set; }

		#endregion

		#region Public Methods

		public DeleteObjectSet() {
			ChangetSetType = EChangetSetType.Delete;
		}

		public override string ToString() {
			return string.Format("OID: '{0}', Deleting Object of Type '{1}'", oid, type);
		}

		#endregion
	}

	/// <summary>
	/// Base change set class, only containing type of change set information.
	/// All different change sets inherit from this one.
	/// </summary>
	[Serializable]
	public abstract class BaseChangetSet {
		#region Public Properties

		public EChangetSetType ChangetSetType { get; set; }

		#endregion
	}

	/// <summary>
	/// Gives the type of a change set,
	/// faster then checking
	/// </summary>
	public enum EChangetSetType {
		New,
		Delete,
		Change,
		ChangeCollection
	}
}